package cn.topevery.garden.dal.util;

import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.topevery.garden.entity.vo.ExcelImportVO;
import cn.topevery.garden.framework.base.BaseEntity;
import hw.topevery.basis.dal.util.SysMapTreeUtil;
import hw.topevery.basis.entity.dto.SysMapTree;
import hw.topevery.framework.web.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ExcelImportUtil {
    /**
     * 解析excel文件
     *
     * @param inputStream    输入流
     * @param clazz          导入benn类型
     * @param filterFunction 数据校验过滤函数
     * @param <T>            待导入数据类型
     * @return
     * @throws Exception
     */
    public static <T extends ExcelImportVO> Map<String, Object> analysisExcel(InputStream inputStream, Class<T> clazz, Predicate<T> filterFunction) throws Exception {
        ImportParams importParams = new ImportParams() {{
            setHeadRows(1);
            setNeedVerify(true);
        }};
        ExcelImportResult<T> result;
        result = cn.afterturn.easypoi.excel.ExcelImportUtil.importExcelMore(inputStream, clazz, importParams);
        // 解析正常，继续校验详细数据
        List<T> parsePassList = result.getList();
        List<T> parseFailList = result.getFailList();
        List<T> verifyFailList = parsePassList.stream().filter(filterFunction).collect(Collectors.toList());
        //移动校验失败的数据
        parsePassList.removeAll(verifyFailList);
        parseFailList.addAll(verifyFailList);
        parsePassList.forEach(vo -> vo.setIsPass(true));
        parseFailList.forEach(vo -> vo.setIsPass(false));
        //将失败的条目也导入作为结果返回
        parsePassList.addAll(parseFailList);
        Map<String, Object> res = new HashMap<>(2);
        res.put("isPass", parseFailList.size() == 0 && parsePassList.size() > 0);
        res.put("data", parsePassList);
        return res;
    }

    /**
     * 校验导入数据的行政区域
     *
     * @param vo                  待导入数据
     * @param errorMessageBuilder 错误信息
     * @param sysMapTreeUtil      区域查询bean
     * @param <T>                 待导入数据类型
     * @return 填写行政区域名是否合法
     */
    public static <T extends ExcelImportVO> boolean verifyArea(T vo, StringBuilder errorMessageBuilder, SysMapTreeUtil sysMapTreeUtil) {
        //校验行政区域
        boolean areaFlag = false;
        //获取区域树
        List<SysMapTree> mapTree = sysMapTreeUtil.getMapTree("CB93996B-7B56-11ED-B8DF-00155DEB0E04");
        if (StringUtils.isNotBlank(vo.getDistractName()) && !CollectionUtils.isEmpty(mapTree)) {
            List<SysMapTree> distractList = mapTree.stream().filter(f -> f.getLabel().equals(vo.getDistractName())).collect(Collectors.toList());
            areaFlag = CollectionUtils.isEmpty(distractList);
            if (!areaFlag) {
                SysMapTree distractTree = distractList.get(0);
                vo.setDistractId(distractTree.getId());
                if (StringUtils.isNotBlank(vo.getStreetName())) {
                    List<SysMapTree> streetList = distractTree.getChildren();
                    List<SysMapTree> street = streetList.stream().filter(f -> f.getLabel().equals(vo.getStreetName())).collect(Collectors.toList());
                    areaFlag = CollectionUtils.isEmpty(street);
                    if (!areaFlag) {
                        SysMapTree streetTree = street.get(0);
                        vo.setStreetId(streetTree.getId());
                        if (StringUtils.isNotBlank(vo.getCommunityName())) {
                            List<SysMapTree> communityList = streetTree.getChildren();
                            List<SysMapTree> community = communityList.stream().filter(f -> f.getLabel().equals(vo.getCommunityName())).collect(Collectors.toList());
                            areaFlag = CollectionUtils.isEmpty(community);
                            if (!areaFlag) {
                                vo.setCommunityId(community.get(0).getId());
                            } else {
                                errorMessageBuilder.append("填写社区不在街道内\t");
                            }
                        }
                    } else {
                        errorMessageBuilder.append("填写街道不在区域内\t");
                    }
                }
            } else {
                errorMessageBuilder.append("区域不存在\t");
            }
        } else {
            areaFlag = true;
        }
        return areaFlag;
    }

    /**
     * 导入excel数据
     *
     * @param voList         待导入数据
     * @param filterFunction 数据过滤函数
     * @param copyFunction   参数复制及类型转换函数
     * @param dbFallback     数据库操作函数
     * @param <T>            待导入数据类型
     * @param <U>            数据库实体类型
     * @return 调用结果
     */
    public static <T extends ExcelImportVO, U extends BaseEntity>
    JsonResult<?> importExcel(List<T> voList, Predicate<T> filterFunction, Function<T, U> copyFunction, Consumer<List<U>> dbFallback) {
        //再次校验前端返回的值，避免之前校验过的数据被修改。
        if (CollectionUtils.isEmpty(voList)) {
            return JsonResult.error("未找到要导入的数据!");
        }
        long failCount = voList.stream().filter(filterFunction).count();
        if (failCount > 0) {
            return JsonResult.error("数据存在异常修改");
        }
        //更新数据到数据库
        List<U> entities = voList.stream().map(copyFunction).collect(Collectors.toList());
        dbFallback.accept(entities);
        return JsonResult.ok("导入成功");
    }
}
